<?php
/**
 * Contians the main FPDF5 Image class.
 *
 * @author Paul Horton <software AT phpsystems.co.uk>
 * @copyright Paul Horton (c) 2008-9
 * @package FPDF5
 * @see http://www.fpdf.org
 * @version $Id: $
 */
namespace com\phpsystems\fpdf5;

/**
 * FPDF-5 Image class.
 *
 * Handles images to put into PDF's.
 *
 * @author Paul Horton <software AT phpsystems.co.uk>
 * @copyright Paul Horton (c) 2008-9
 * @package FPDF5
 */
abstract class FPDF5_Image {

   const COLOUR_SPACE_RGB = 1;
   const COLOUR_SPACE_CMYK = 2;
   const COLOUR_SPACE_GRAY = 3;

   /**
    * Image filename.
    *
    * @var String
    */
   private $str_filename = '';

   /**
    * Original width of source image.
    *
    * @var Integer
    */
   protected $int_image_width = -1;

   /**
    * Original height of source image.
    *
    * @var Integer
    */
   protected $int_image_height = -1;

   /**
    * Requested rendering width of image.
    *
    * @var FPDF5_Unit
    */
   protected $obj_render_width = null;

   /**
    * Requested rendering height of image.
    *
    * @var FPDF5_Unit
    */
   protected $obj_render_height = null;

   /**
    * Colour space of original image.
    *
    * @var Integer
    */
   protected $int_colour_space = -1;

   /**
    * Bits per colour.
    *
    * @var Integer
    */
   protected $int_bits = -1;

   /**
    * Palette.
    *
    * @var String
    */
   protected $str_palette = '';

   /**
    * Filter
    *
    * @var String
    */
   protected $str_filter = '';

   /**
    * PDF Parameters.
    *
    * @var String
    */
   protected $str_params = '';

   /**
    * Image data.
    *
    * @var String
    */
   protected $str_image_data = null;

   /**
    * Call this to contruct any FPDF5_Image type.
    *
    * @param String $str_filename
    * @return FPDF5_Image
    * @throws FPDF5_Exception
    */
   public static function create($str_filename) {
      if (!file_exists($str_filename)) {
         throw new FPDF5_Exception(__METHOD__ . ': Image at file ' . $str_filename . ' does not exist!');
      }

      // Try to determine image type
      $arr_image_details = @getimagesize($str_filename);
      if ($arr_image_details === false) {
         throw new FPDF5_Exception(__METHOD__ . ': Could not ascertain image details from file ' . $str_filename);
      }

      $obj_image = null;
      switch ($arr_image_details[2]) {
         case IMAGETYPE_JPEG:
            $obj_image = new \com\phpsystems\fpdf5\image\FPDF5_Image_JPEG($str_filename);
            break;
         case IMAGETYPE_PNG:
            $obj_image = new \com\phpsystems\fpdf5\image\FPDF5_Image_PNG($str_filename);
            break;
         default:
            throw new FPDF5_Exception(__METHOD__ . ': ' . $str_filename . ' contains an unsupported image type (' . $arr_image_details[2] . ').');
      }

      return $obj_image;
   }

   /**
    * Constructor.
    *
    * @param String $str_filename
    */
   public final function __construct($str_filename) {
      $this->str_filename = $str_filename;
      $this->init();
      $this->parse_image_data();
   }

   /**
    * Get original image filename.
    *
    * @return String
    */
   public final function get_image_filename() {
      return $this->str_filename;
   }

   /**
    * Get image data.
    *
    * @return String
    */
   public final function get_image_data() {
      return $this->str_image_data;
   }

   /**
    * Gets a 'handle' for this FPDF5_Image.
    *
    * @return String
    */
   public final function get_image_handle() {
      return strtoupper($this->get_image_filename());
   }

   /**
    * Get original image width.
    *
    * @return Integer
    */
   public final function get_image_width() {
      return $this->int_image_width;
   }

   /**
    * Get original image height.
    *
    * @return Integer
    */
   public final function get_image_height() {
      return $this->int_image_height;
   }

   /**
    * Get rendering image height.
    *
    * @return FPDF5_Unit
    */
   public final function get_render_height() {
      if (!is_null($this->obj_render_height)) {
         error_log("NOT NULL: " . print_r($this->obj_render_height, true));
         return $this->obj_render_height;
      } else {
         // Auto-scale
         $flt_height = $this->get_render_width()->get_unit_pt_value() * ($this->get_image_height() / $this->get_image_width());
         error_log("$flt_height");
         return FPDF5_Unit::create($flt_height, FPDF5_Unit::UNIT_PT);
      }
//      } else {
//         return $this->get_image_height();
//      }
   }

   /**
    * Get rendering image width.
    *
    * @return FPDF5_Unit
    */
   public final function get_render_width() {
      if (!is_null($this->obj_render_width)) {
         return $this->obj_render_width;
      } else {
         // Auto-scale
         $flt_width = $this->get_render_height()->get_unit_pt_value() * ($this->get_image_width() / $this->get_image_height());
         return FPDF5_Unit::create($flt_width, FPDF5_Unit::UNIT_PT);
      }
//
//      if ($this->int_render_width > 0) {
//         return $this->int_render_width;
//      } else if ($this->int_render_width > 0) {
//         // Auto-scale
//         return $this->get_render_height() * ($this->get_image_width() / $this->get_image_height());
//      } else {
//         return $this->get_image_width();
//      }
   }

   /**
    * Get original image colour space.
    *
    * @return Integer
    */
   public final function get_colour_space() {
      return $this->int_colour_space;
   }

   /**
    * Get original image bit rate.
    *
    * @return Integer
    */
   public final function get_bits() {
   	return $this->int_bits;
   }

   /**
    * Get palette.
    *
    * @return String
    */
   public final function get_palette() {
      return $this->str_palette;
   }

   /**
    * Get filter.
    *
    * @return String
    */
   public final function get_filter() {
      return $this->str_filter;
   }

   /**
    * Get PDF data parameters.
    *
    * @return String
    */
   public final function get_pdf_parameters() {
      return $this->str_params;
   }

   /**
    * Set the requested rendering height of the iamge.
    *
    * @param FPDF5_Unit $obj_height
    */
   public final function set_render_height(FPDF5_Unit $obj_height) {
      $this->obj_render_height = $obj_height;
   }

   /**
    * Set the requested rendering width of the iamge.
    *
    * @param FPDF5_Unit $obj_width
    */
   public final function set_render_width(FPDF5_Unit $obj_width) {
      $this->obj_render_width = $obj_width;
   }

   /**
    * Initialisation function.
    *
    * @throws FPDF5_Exception
    */
   protected final function init() {
      $arr_image_data = @getimagesize($this->str_filename);
      $this->int_image_width = $arr_image_data[0];
      $this->int_image_height = $arr_image_data[1];
      $this->int_bits = $arr_image_data['bits'];
      switch ($arr_image_data['channels']) {
         case 3:
         case '3':
            $this->int_colour_space = self::COLOUR_SPACE_RGB;
            break;
         case 4:
         case '4':
            $this->int_colour_space = self::COLOUR_SPACE_CMYK;
            break;
         default:
            error_log(print_r($arr_image_data, true));
            throw new FPDF5_Exception(__METHOD__ . ': Unknown colour space for image: ' . $arr_image_data[2]);
      }
   }

   /**
    * Reads N bytes from the image data.
    *
    * @param resource $res_file
    * @param Integer $int_n_bytes
    * @return String
    */
   protected final function read_stream($res_file, $int_n_bytes) {
      $str_data = '';
   	while($int_n_bytes > 0 && !feof($res_file)) {
   		$str_data_got = fread($res_file, $int_n_bytes);
   		if($str_data_got === false) {
   			throw new FPDF5_Exception(__METHOD__ . ': Error while reading image data stream.');
   		}
   		$int_n_bytes -= strlen($str_data_got);
   		$str_data .= $str_data_got;
   	}
   	if($int_n_bytes > 0) {
   		throw new FPDF5_Exception(__METHOD__ . ': Unexpected end of image data stream.');
   	}
   	return $str_data;
   }

   /**
    * Parse image data.
    *
    */
   protected abstract function parse_image_data();
}